/**
 * 
 */
package com.gr.staffpm.pages.schedule.model;

import java.io.Serializable;

import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Duration;
import org.joda.time.Period;
import org.joda.time.PeriodType;


/**
 * @author Graham Rhodes 19 Mar 2011 23:47:03
 */
public class Event implements Serializable, Comparable<Event> {

    private static final long serialVersionUID = 1L;
    private String title = "";
    private DateTime start;
    private DateTime end;
    private boolean allDay = false;
    private int reminder = 0;
    private boolean addedToEventPanel = false;
    private Calendar calendar = new Calendar(0);

    //private final Logger log = LoggerFactory.getLogger(getClass());

    public String getTitle() {
        return title;
    }

    public DateTime getStart() {
        return start;
    }

    public DateTime getEnd() {
        return end;
    }

    public boolean isAllDay() {
        return allDay;
    }

    public boolean isAddedToEventPanel() {
        return addedToEventPanel;
    }

    public boolean isEmpty() {
        return false;
    }

    public boolean isMore() {
        return false;
    }

    public int getReminder() {
        return reminder;
    }

    public Calendar getCalendar() {
        return calendar;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setStart(DateTime start) {
        this.start = start;
    }

    public void setEnd(DateTime end) {
        this.end = end;
    }

    public void setAllDay(boolean allDay) {
        this.allDay = allDay;
    }

    public void setReminder(int reminder) {
        this.reminder = reminder;
    }

    public void setAddedToEventPanel(boolean addedToEventPanel) {
        this.addedToEventPanel = addedToEventPanel;
    }

    public void setCalendar(Calendar calendar) {
        this.calendar = calendar;
    }

    //Convenience methods

    /**
     * Returns true if first this is longer than the second
     */
    public boolean isLonger(Event e2) {
        Duration e1Dur = new Duration(start, end);
        Duration e2Dur = new Duration(e2.getStart(), e2.getEnd());
        return e1Dur.isLongerThan(e2Dur);
    }

    public boolean startsBefore(Event e2) {
        return start.isBefore(e2.getStart());
    }

    public boolean startsOnOrBefore(DateTime weekStartDate) {
        boolean startsOnOrBefore = !start.withTime(0, 0, 0, 0).isAfter(weekStartDate.withTime(0, 0, 0, 0));
        boolean endsOnOrAfter = !end.withTime(0, 0, 0, 0).isBefore(weekStartDate.withTime(0, 0, 0, 0));
        return (startsOnOrBefore && endsOnOrAfter);
    }

    @Override
    public int compareTo(Event e2) {
        Duration e1Dur = new Duration(start, end);
        Duration e2Dur = new Duration(e2.getStart(), e2.getEnd());
        return e2Dur.compareTo(e1Dur);
    }

    public boolean endsBeforeEndOfWeek(DateTime endOfWeek) {
        return end.isBefore(endOfWeek);
    }

    public int getDaysSpannedTo(DateTime weekEnd) {
        int dur = new Period(start.withTime(0, 0, 0, 0), end.withTime(0, 0, 0, 0), PeriodType.days()).getDays();
        if (end.withTime(0, 0, 0, 0).isAfter(weekEnd.withTime(0, 0, 0, 0))) {
            dur = new Period(start.withTime(0, 0, 0, 0), weekEnd.withTime(0, 0, 0, 0), PeriodType.days()).getDays();
        } else if (end.getDayOfWeek() != DateTimeConstants.SUNDAY) {
            dur++;
        }


        return (dur > 7 ? 7 : (dur <= 0 ? 1 : dur));
    }

    public boolean isAllDayStartingBefore(DateTime dt) {
        return allDay && (start.getDayOfMonth() < dt.getDayOfMonth());
    }

    public boolean isAllDayNotEndingStarting(DateTime dt) {
        return allDay && (start.getDayOfMonth() == dt.getDayOfMonth() && (end.getDayOfMonth() > dt.getDayOfMonth()));
    }

    public boolean startsOnOrAfter(DateTime eventStartDate) {
        return !start.withTime(0, 0, 0, 0).isBefore(eventStartDate.withTime(0, 0, 0, 0));
    }

    public boolean endsOnOrBefore(DateTime eventEndDate) {
        return !end.withTime(0, 0, 0, 0).isAfter(eventEndDate.withTime(0, 0, 0, 0));
    }

    public boolean endsOnOrAfter(DateTime eventEndDate) {
        return !end.withTime(0, 0, 0, 0).isBefore(eventEndDate.withTime(0, 0, 0, 0));
    }

    public boolean startsBefore(DateTime dt) {
        return start.withTime(0, 0, 0, 0).isBefore(dt.withTime(0, 0, 0, 0));
    }

    public boolean endsAfter(DateTime dt) {
        return end.withTime(0, 0, 0, 0).isAfter(dt.withTime(0, 0, 0, 0));
    }

    public int getDaysSpannedFrom(DateTime weekStart, DateTime weekEnd) {
        int dur = new Period(weekStart.withTime(0, 0, 0, 0), end.withTime(0, 0, 0, 0), PeriodType.days()).getDays();
        //log.info(dur + " Days between " + weekStart.withTime(0, 0, 0, 0).toString() + " & " + end.withTime(0, 0, 0, 0).toString());
        if (end.withTime(0, 0, 0, 0).isAfter(weekEnd.withTime(0, 0, 0, 0))) {
            dur = new Period(start.withTime(0, 0, 0, 0), weekEnd.withTime(0, 0, 0, 0), PeriodType.days()).getDays();
            //log.info(dur + " Days between " + weekStart.withTime(0, 0, 0, 0).toString() + " & " + weekEnd.withTime(0, 0, 0, 0).toString());
        } else if (end.getDayOfWeek() != DateTimeConstants.SUNDAY) {
            //log.info("Doesn't end on a Sunday, add a day.");
            dur++;
        }
        return (dur > 7 ? 7 : (dur <= 0 ? 1 : dur));
    }

}
